

import base64
import json
import httpx
import os
from datetime import datetime, timedelta
from dataclasses import dataclass, asdict, field
from typing import Optional, Dict, Any, List


OUTPUT_JSONL = "roma_create_job.jsonl"
CACHED_TOKEN_PATH = "cached_roma_token.token"
TOKEN_EXPIRE_DELTA = timedelta(hours=23, minutes=50)

"""
ROMA Get train info:
{
	"success": true,
	"msg": "",
	...
	"versionInfo": {
        ...
		"statusCode": "12"
        ...
	}
}

STATUS MAP， 名称：statusCode  类型： String
'ALL': '全部状态',
'000': '等待中',
'001': '云创建失败',
'0': '状态未知',
'1': '初始化',
'2': '创建中',
'3': '创建失败',
'4': '提交中',
'5': '提交失败',
'6': '删除失败',
'7': '排队中',
'8': '运行中',
'9': '停止中',
'10': '已完成',
'11': '运行失败',
'12': '已停止',
'13': '创建失败（资源不足）',
'14': '已丢失',
'15': '扩容中',
'18': '审核作业初始化',
'19': '审核作业正在运行中',
'21': '审核作业失败',
'23': '异常状态',
'24': '下载数据中',
'25': '被抢占',
'26': 'OS排队中',
'MISS': '状态缺失',
'success': '成功',
'fail': '失败',
'miss': '状态缺失',
'TERMINATED':'运行成功',
'RUNNING':'运行中',
'ERROR':'运行失败'

"""

""" 
# Roma Url:
https://csb.roma.huawei.com/csb/rest/saas/ei/eiWizard/train/job/create?appid=com.app.bmc.ai.aicase&vendor=HEC&region=cn-southwest-2&trainApiVersion=V2&TENANTSPACEID=CSB

# Roma Request:
{
  "name": "7Bv5-s-sft_sf_stg1-26w_M2M_LowR_13kAR-250806-copy-6784",
  "desc": "exp-m2m-low",
  "config": {
    "logUrl": "/bucket-tte-guiyang/SFT_LOG_CENTRAL/7Bv5-s-sft_sf_stg1-26w_M2M_LowR_13kAR-250806/",
    "logUrlBucketId": "66382e7e-f2d6-4d4a-91f8-97bb63cb044a",
    "preVersionId": "",
    "dataSources": "private",
    "annotations": {
      "faultToleranceJobRetryNum": 1,
      "faultToleranceHangRetry": false,
      "faultToleranceProcessRetryNum": "2",
      "faultToleranceJobUnconditionalRetry": false
    },
    "experimentId": "",
    "environments": {
      "DEBUG_ROUTE_PLAN": "true",
      "ROUTE_PLAN": "true"
    },
    "trainUrl": "/bucket-tte-guiyang/SFT_CKPT_CENTRAL/7Bv5-s-sft_sf_stg1-26w_M2M_LowR_13kAR-250806/",
    "trainUrlBucketId": "66382e7e-f2d6-4d4a-91f8-97bb63cb044a",
    "outputs": [
      {
        "dataType": "OBS",
        "dataSetId": "",
        "dataSetVersionId": "",
        "dataSetName": "",
        "dataSetVersion": "",
        "prefetchToLocal": false,
        "obsUrl": "/bucket-tte-guiyang/SFT_CKPT_CENTRAL/7Bv5-s-sft_sf_stg1-26w_M2M_LowR_13kAR-250806/",
        "obsBucketUid": "66382e7e-f2d6-4d4a-91f8-97bb63cb044a",
        "name": "train_url",
        "accessMethod": "parameter",
        "parameter": {
          "value": "/home/ma-user/modelarts/outputs/train_url_0"
        },
        "description": "数据输出"
      }
    ],
    "policy": "regular",
    "inputs": [],
    "taskMode": "single",
    "params": [
      {
        "key": "data-url",
        "value": "s3://bucket-tte-guiyang/SFT_DATA_CENTRAL/7Bv5-s-sft_sf_stg1-26w_M2M_LowR_13kAR-250806/merged/",
        "paramType": "common"
      },
      {
        "key": "dataset-name",
        "value": "sft",
        "paramType": "common"
      },
      {
        "key": "device",
        "value": "B2",
        "paramType": "common"
      },
      {
        "key": "global-batch-size",
        "value": "64",
        "paramType": "common"
      },
      {
        "key": "load-ckpt-path",
        "value": "s3://bucket-tte-guiyang/BASELINE_CKPT_CENTRAL/7bv5_0703_stage1_merged_0703_stage1_rm_dup/",
        "paramType": "common"
      },
      {
        "key": "model",
        "value": "BMC_APP_7BV5_SFT_rp16e6_lr5e-6_mcore",
        "paramType": "common"
      },
      {
        "key": "profiling-path",
        "value": "/home/ma-user/modelarts/outputs/train_url_0",
        "paramType": "common"
      },
      {
        "key": "save-interval",
        "value": "200",
        "paramType": "common"
      },
      {
        "key": "sequence-lens",
        "value": "32K",
        "paramType": "common"
      },
      {
        "key": "train-iters",
        "value": "2800",
        "paramType": "common"
      }
    ],
    "algoType": "selfdefined",
    "selfDefinedCommandType": "customCommand",
    "appUrl": "/bucket-tte-guiyang/SFT_CODE_CENTRAL/PanGu-7B-Reasoner/pangu_sophon_pytorch_develop/",
    "appUrlBucketId": "66382e7e-f2d6-4d4a-91f8-97bb63cb044a",
    "engineRunUser": "",
    "userImageUid": "115750ea-bda0-4e1a-b4b1-3abd759241bc",
    "userImageVersionUid": "967e6e91-0e0e-4c21-9829-0b38f0a81cf8",
    "userCommand": "cd /home/ma-user/modelarts/user-job-dir/pangu_sophon_pytorch_develop/PanGu && source ma-pre-start.sh && cd /home/ma-user/modelarts/user-job-dir/pangu_sophon_pytorch_develop/PanGu && python launch.py",
    "poolType": "private",
    "poolUid": "bac439dd-b394-49ab-8859-37d08d45561e",
    "specName": "os-roma-cnst2-313t-c015-siye-1",
    "flavorCode": "modelarts.pool.visual.xlarge",
    "workNum": 2,
    "sharedPool": "yes",
    "nas": [],
    "notify": "yes",
    "voiceNotify": false,
    "priority": "3"
  },
  "jobKind": "job",
  "tags": [],
  "parentJobUid": "df635bef-6522-4b9e-a6d6-3a5f8c099c91"
}



# Roma Response:
{
    "success": true,
    "msg": "",
    "detail": null,
    "includingDetail": false,
    "errorCode": null,
    "id": "aa66f7cd-2e4c-4aaf-83d4-9a95c60403ec",
    "versionUid": "d074820c-d459-4f53-a656-7da92d34683f",
    "scheduleId": null
}
"""

@dataclass
class Parameter:
    """参数配置"""
    value: str

@dataclass
class Output:
    """输出数据配置"""
    dataType: str = "OBS"
    dataSetId: str = ""
    dataSetVersionId: str = ""
    dataSetName: str = ""
    dataSetVersion: str = ""
    prefetchToLocal: bool = False
    obsUrl: str = ""
    obsBucketUid: str = ""
    name: str = ""
    accessMethod: str = "parameter"
    parameter: Optional[Parameter] = None
    description: str = "数据输出"

@dataclass
class Param:
    """训练参数配置"""
    key: str
    value: str
    paramType: str = "common"

@dataclass
class Annotations:
    """训练作业注释配置"""
    faultToleranceJobRetryNum: int = 1
    faultToleranceHangRetry: bool = False
    faultToleranceProcessRetryNum: str = "2"
    faultToleranceJobUnconditionalRetry: bool = False

@dataclass
class Config:
    """训练作业配置"""
    # 基础配置
    logUrl: str = ""  # 训练作业的日志OBS输出路径URL
    logUrlBucketId: str = ""  # 训练作业的日志OBS输出路径URL的桶id
    preVersionId: str = ""
    dataSources: str = "private"
    annotations: Annotations = field(default_factory=Annotations)
    experimentId: str = ""  # 实验ID
    
    # 环境变量配置
    environments: Dict[str, str] = field(default_factory=dict)
    
    # 训练URL配置
    trainUrl: str = ""
    trainUrlBucketId: str = ""
    
    # 输入输出配置
    outputs: List[Output] = field(default_factory=list)
    inputs: List[Any] = field(default_factory=list)
    
    # 任务配置
    policy: str = "regular"
    taskMode: str = "single"
    params: List[Param] = field(default_factory=list)
    
    # 算法配置
    algoType: str = "selfdefined"
    selfDefinedCommandType: str = "customCommand"
    appUrl: str = ""  # 代码目录
    appUrlBucketId: str = ""
    
    # 执行配置
    engineRunUser: str = ""
    userImageUid: str = ""
    userImageVersionUid: str = ""
    userCommand: str = ""
    
    # 资源配置
    poolType: str = "private"
    poolUid: str = ""
    specName: str = ""
    flavorCode: str = ""  # 训练作业资源规格id
    workNum: int = 1  # 计算节点个数
    sharedPool: str = "yes"  # 是否是共享专属池
    
    # 存储配置
    nas: List[Any] = field(default_factory=list)
    
    # 通知配置
    notify: str = "yes"
    priority: str = "3"
    


@dataclass
class RomaCreateRequest:
    """创建训练作业请求"""
    name: str
    config: Config
    desc: str = ""
    jobKind: str = "job"
    tags: List[str] = field(default_factory=list)
    parentJobUid: str = ""
    userId: str = ""


    def to_json(self) -> str:
        """将请求转换为JSON字符串"""
        request_body = self._build_request_body()
        return json.dumps(request_body, indent=2, ensure_ascii=False)
    
    def get_request_body(self) -> Dict[str, Any]:
        """获取请求体字典"""
        return self._build_request_body()
    
    def _build_request_body(self) -> Dict[str, Any]:
        """构建请求体，排除HTTP配置字段"""
        request_body = {
            "name": self.name,
            "desc": self.desc,
            "config": asdict(self.config),
            "jobKind": self.jobKind,
            "tags": self.tags,
            "userId": self.userId,
        }
        
        # 只有当parentJobUid不为空时才包含
        if self.parentJobUid:
            request_body["parentJobUid"] = self.parentJobUid
            
        return request_body
    

    @classmethod
    def from_template(cls) -> 'RomaCreateRequest':
        """从文档中的模板创建实例"""
        # 创建输出配置
        train_output = Output(
            dataType="OBS",
            dataSetId="",
            dataSetVersionId="",
            dataSetName="",
            dataSetVersion="",
            prefetchToLocal=False,
            obsUrl="/bucket-tte-guiyang/SFT_CKPT_CENTRAL/7Bv5-s-sft_sf_stg1-26w_M2M_LowR_13kAR-250806/",
            obsBucketUid="66382e7e-f2d6-4d4a-91f8-97bb63cb044a",
            name="train_url",
            accessMethod="parameter",
            parameter=Parameter(value="/home/ma-user/modelarts/outputs/train_url_0"),
            description="数据输出"
        )
        
        # 创建训练参数列表
        training_params = [
            Param(key="data-url", value="s3://bucket-tte-guiyang/SFT_DATA_CENTRAL/7Bv5-s-sft_sf_stg1-26w_M2M_LowR_13kAR-250806/merged/"),
            Param(key="dataset-name", value="sft"),
            Param(key="device", value="B2"),
            Param(key="global-batch-size", value="64"),
            Param(key="load-ckpt-path", value="s3://bucket-tte-guiyang/BASELINE_CKPT_CENTRAL/7bv5_0703_stage1_merged_0703_stage1_rm_dup/"),
            Param(key="model", value="BMC_APP_7BV5_SFT_rp16e6_lr5e-6_mcore"),
            Param(key="profiling-path", value="/home/ma-user/modelarts/outputs/train_url_0"),
            Param(key="save-interval", value="200"),
            Param(key="sequence-lens", value="32K"),
            Param(key="train-iters", value="2800")
        ]
        
        # 创建环境变量
        environments = {
            "DEBUG_ROUTE_PLAN": "true",
            "ROUTE_PLAN": "true"
        }
        
        # 创建注释配置
        annotations = Annotations(
            faultToleranceJobRetryNum=1,
            faultToleranceHangRetry=False,
            faultToleranceProcessRetryNum="2",
            faultToleranceJobUnconditionalRetry=False
        )
        
        # 创建配置对象
        config = Config(
            logUrl="/bucket-tte-guiyang/SFT_LOG_CENTRAL/7Bv5-s-sft_sf_stg1-26w_M2M_LowR_13kAR-250806/",
            logUrlBucketId="66382e7e-f2d6-4d4a-91f8-97bb63cb044a",
            preVersionId="",
            dataSources="private",
            annotations=annotations,
            experimentId="",
            environments=environments,
            trainUrl="/bucket-tte-guiyang/SFT_CKPT_CENTRAL/7Bv5-s-sft_sf_stg1-26w_M2M_LowR_13kAR-250806/",
            trainUrlBucketId="66382e7e-f2d6-4d4a-91f8-97bb63cb044a",
            outputs=[train_output],
            policy="regular",
            inputs=[],
            taskMode="single",
            params=training_params,
            algoType="selfdefined",
            selfDefinedCommandType="customCommand",
            appUrl="/bucket-tte-guiyang/SFT_CODE_CENTRAL/PanGu-7B-Reasoner/pangu_sophon_pytorch_develop/",
            appUrlBucketId="66382e7e-f2d6-4d4a-91f8-97bb63cb044a",
            engineRunUser="",
            userImageUid="115750ea-bda0-4e1a-b4b1-3abd759241bc",
            userImageVersionUid="967e6e91-0e0e-4c21-9829-0b38f0a81cf8",
            userCommand="cd /home/ma-user/modelarts/user-job-dir/pangu_sophon_pytorch_develop/PanGu && source ma-pre-start.sh && cd /home/ma-user/modelarts/user-job-dir/pangu_sophon_pytorch_develop/PanGu && python launch.py",
            poolType="common",
            poolUid="bac439dd-b394-49ab-8859-37d08d45561e",
            specName="os-roma-d910b-c006-siye-rl",
            flavorCode="modelarts.pool.visual.8xlarge",
            workNum=1,
            sharedPool="yes",
            nas=[],
            notify="yes",
            priority="3"
        )
        
        return cls(
            name="7Bv5-s-sft_sf_stg1-26w_M2M_LowR_13kAR-250806-copy-test",
            desc="exp-m2m-low",
            config=config,
            jobKind="job",
            tags=[
                "c6c05f8a-5417-11f0-b874-fa163e8e9128",
                "c6d4c3dc-5417-11f0-b874-fa163e8e9128"
            ],
            parentJobUid="df635bef-6522-4b9e-a6d6-3a5f8c099c91",
            userId="l30038643"
        )

def reuse_or_fetch_token(account_name, account_secret):
    """
    Return cached token if not expired, else fetch a new one and cache with timestamp.
    """
    now = datetime.now(datetime.now().tzinfo)
    print("Now is ", now)
    # Check for existing cached token
    if os.path.exists(CACHED_TOKEN_PATH):
        with open(CACHED_TOKEN_PATH, "r", encoding="utf-8") as f:
            try:
                cached = json.load(f)
                ts = cached.get("timestamp")
                if ts:
                    ts_dt = datetime.fromisoformat(ts)
                    if now - ts_dt < TOKEN_EXPIRE_DELTA and "access_token" in cached:
                        print("✅ Using cached token.")
                        return cached["access_token"]
            except Exception as e:
                print(f"⚠️ Failed to load cached token: {e}")

    # Fetch new token
    url = "https://csb.roma.huawei.com/csb/v2/enterprise/tenant/rest/csbiam/auth/enterprise-token"
    headers = {"Content-Type": "application/json"}
    data = {
        "data": {
            "type": "JWT-Token",
            "attributes": {
                "integrationAccountName": account_name,
                "integrationAccountSecret": account_secret,
            },
        }
    }
    with httpx.Client(proxy=None, verify=False) as client:
        response = client.post(url, headers=headers, json=data)
        response.raise_for_status()
        access_token = response.json()
        # Cache with timestamp
        with open(CACHED_TOKEN_PATH, "w", encoding="utf-8") as f:
            cache_content = {
                "timestamp": now.isoformat(),
                "access_token": access_token["accessToken"],
            }
            json.dump(cache_content, f, ensure_ascii=False)
            f.write("\n")
        print("✅ Cached new token to", CACHED_TOKEN_PATH)
        return access_token['accessToken']


def roma_create_request():
    print(f"Calling ROMA API to create training jobs, appending to {OUTPUT_JSONL}...")
    url = "https://apigw.huawei.com/api/csb/roma-aistudio/train/job/create"
    token_to_use = reuse_or_fetch_token(
        account_name="BMC_API_USER",
        account_secret="AESGCM:2856B514BE721213DBEADA0A5F37BD15:57AA692302F16DE42F5914D82F45B8F94EA1635A9D72912911C19BD748F63CD6E33C34BDB2AFD98DDF67A45F1A084DF2E7DED0C3",
    )
    print(f'Got token to use {token_to_use}')
    headers = {
        "Content-Type": "application/json",
        "Authorization": token_to_use,
        "X-HW-ID": "com.huawei.ipd.noproduct.tenant_z00515901.BJ",  # 这就是his gateway 绑定的应用id 而非roma的 bmc.ai.case，对所有roma应用通用
        "X-HW-APPKEY": "31y1UZJvij3YQ9QpZGk6dw==",  # apigateway api key 应用创建者在这里获取 https://console.his.huawei.com/apigw_portals/#/app/list
    }

    # Set your parameter values here
    appid = "com.app.bmc.ai.aicase"
    trainApiVersion = "V2"
    # jobType = "train"
    region = "cn-southwest-2"
    vendor = "HEC"
    roma_create_request = RomaCreateRequest.from_template()
    request_body = roma_create_request.get_request_body()

    query_params = {
        "appid": appid,
        "trainApiVersion": trainApiVersion,
        # "jobType": jobType,
        "region": region,
        "vendor": vendor,
        "TENANTSPACEID":"CSB",
    }

    print("Request param:", roma_create_request.to_json())
    with httpx.Client(proxy=None, verify=False) as client:
        response = client.post(url, headers=headers, params=query_params, json=request_body)
        print("response  "* 3, response.status_code,  response.json())
        response.raise_for_status()
        data = response.json()
        with open(OUTPUT_JSONL, "w", encoding="utf-8") as f:
            f.write(json.dumps(data, ensure_ascii=False) + "\n")
        print("✅ Appended JSON response to", OUTPUT_JSONL)
        return data

def roma_get_train():
    INFO_OUTPUT_JSONL = "roma_get_info.jsonl"
    url = "https://apigw.huawei.com/api/csb/roma-aistudio/train/job/info"
    token_to_use = reuse_or_fetch_token(
        account_name="BMC_API_USER",
        account_secret="AESGCM:2856B514BE721213DBEADA0A5F37BD15:57AA692302F16DE42F5914D82F45B8F94EA1635A9D72912911C19BD748F63CD6E33C34BDB2AFD98DDF67A45F1A084DF2E7DED0C3",
    )
    print(f'Got token to use {token_to_use}')
    headers = {
        "Content-Type": "application/json",
        "Authorization": token_to_use,
        "X-HW-ID": "com.huawei.ipd.noproduct.tenant_z00515901.BJ",  # 这就是his gateway 绑定的应用id 而非roma的 bmc.ai.case，对所有roma应用通用
        "X-HW-APPKEY": "31y1UZJvij3YQ9QpZGk6dw==",  # apigateway api key 应用创建者在这里获取 https://console.his.huawei.com/apigw_portals/#/app/list
    }

    # Set your parameter values here
    query_params = {
        "versionid":"d074820c-d459-4f53-a656-7da92d34683f",
    }

    with httpx.Client(proxy=None, verify=False) as client:
        response = client.get(url, headers=headers, params=query_params)
        print("response  "* 3, response.status_code,  response.json())
        response.raise_for_status()
        data = response.json()
        with open(INFO_OUTPUT_JSONL, "w", encoding="utf-8") as f:
            f.write(json.dumps(data, ensure_ascii=False) + "\n")
        print("✅ Appended JSON response to", INFO_OUTPUT_JSONL)
        return data


def roma_stop_train():
    INFO_OUTPUT_JSONL = "roma_stop_info.jsonl"
    url = "https://apigw.huawei.com/api/csb/roma-aistudio/train/job/stop"
    token_to_use = reuse_or_fetch_token(
        account_name="BMC_API_USER",
        account_secret="AESGCM:2856B514BE721213DBEADA0A5F37BD15:57AA692302F16DE42F5914D82F45B8F94EA1635A9D72912911C19BD748F63CD6E33C34BDB2AFD98DDF67A45F1A084DF2E7DED0C3",
    )
    print(f'Got token to use {token_to_use}')
    headers = {
        "Content-Type": "application/json",
        "Authorization": token_to_use,
        "X-HW-ID": "com.huawei.ipd.noproduct.tenant_z00515901.BJ",  # 这就是his gateway 绑定的应用id 而非roma的 bmc.ai.case，对所有roma应用通用
        "X-HW-APPKEY": "31y1UZJvij3YQ9QpZGk6dw==",  # apigateway api key 应用创建者在这里获取 https://console.his.huawei.com/apigw_portals/#/app/list
    }

    # Set your parameter values here
    query_params = {
        "id":"084c9ca4-8f10-48c4-a989-bca60cd48d40", # 训练作业版本ID（trainVersionId）。
    }

    with httpx.Client(proxy=None, verify=False) as client:
        response = client.post(url, headers=headers, params=query_params)
        print("response  "* 3, response.status_code,  response.json())
        response.raise_for_status()
        data = response.json()
        with open(INFO_OUTPUT_JSONL, "w", encoding="utf-8") as f:
            f.write(json.dumps(data, ensure_ascii=False) + "\n")
        print("✅ Appended JSON response to", INFO_OUTPUT_JSONL)
        return data

def roma_delete_train():
    INFO_OUTPUT_JSONL = "roma_delete_info.jsonl"
    url = "https://apigw.huawei.com/api/csb/roma-aistudio/train/job/delete"
    token_to_use = reuse_or_fetch_token(
        account_name="BMC_API_USER",
        account_secret="AESGCM:2856B514BE721213DBEADA0A5F37BD15:57AA692302F16DE42F5914D82F45B8F94EA1635A9D72912911C19BD748F63CD6E33C34BDB2AFD98DDF67A45F1A084DF2E7DED0C3",
    )
    print(f'Got token to use {token_to_use}')
    headers = {
        "Content-Type": "application/json",
        "Authorization": token_to_use,
        "X-HW-ID": "com.huawei.ipd.noproduct.tenant_z00515901.BJ",  # 这就是his gateway 绑定的应用id 而非roma的 bmc.ai.case，对所有roma应用通用
        "X-HW-APPKEY": "31y1UZJvij3YQ9QpZGk6dw==",  # apigateway api key 应用创建者在这里获取 https://console.his.huawei.com/apigw_portals/#/app/list
    }

    # Set your parameter values here
    query_params = {
        "id":"084c9ca4-8f10-48c4-a989-bca60cd48d40", # 待删除训练作业的Uid（JOB id）。
    }

    with httpx.Client(proxy=None, verify=False) as client:
        response = client.delete(url, headers=headers, params=query_params)
        print("response  "* 3, response.status_code,  response.json())
        response.raise_for_status()
        data = response.json()
        with open(INFO_OUTPUT_JSONL, "w", encoding="utf-8") as f:
            f.write(json.dumps(data, ensure_ascii=False) + "\n")
        print("✅ Appended JSON response to", INFO_OUTPUT_JSONL)
        return data

def roma_list_event():
    INFO_OUTPUT_JSONL = "roma_list_event.jsonl"
    url = "https://apigw.huawei.com/api/csb/roma-aistudio/train/event/list"
    token_to_use = reuse_or_fetch_token(
        account_name="BMC_API_USER",
        account_secret="AESGCM:2856B514BE721213DBEADA0A5F37BD15:57AA692302F16DE42F5914D82F45B8F94EA1635A9D72912911C19BD748F63CD6E33C34BDB2AFD98DDF67A45F1A084DF2E7DED0C3",
    )
    print(f'Got token to use {token_to_use}')
    headers = {
        "Content-Type": "application/json",
        "Authorization": token_to_use,
        "X-HW-ID": "com.huawei.ipd.noproduct.tenant_z00515901.BJ",  # 这就是his gateway 绑定的应用id 而非roma的 bmc.ai.case，对所有roma应用通用
        "X-HW-APPKEY": "31y1UZJvij3YQ9QpZGk6dw==",  # apigateway api key 应用创建者在这里获取 https://console.his.huawei.com/apigw_portals/#/app/list
    }

    # Set your parameter values here
    query_params = {
        "version_uid":"084c9ca4-8f10-48c4-a989-bca60cd48d40", # 训练作业版本id
        "page_num": 10,
        "page_size": 1,
        "order": "desc", # 按时间排序（asc/desc），默认desc
        "level": "Info", # 事件类型（Info/Warning/Error），默认全部显示
        # "start_time": "", # 查询开始时间，默认作业创建时间
        # "end_time": "" #查询结束时间，默认作业创建时间 +24h(Unix Timestamp)
    }

    with httpx.Client(proxy=None, verify=False) as client:
        response = client.get(url, headers=headers, params=query_params)
        print("response  "* 3, response.status_code,  response.json())
        response.raise_for_status()
        data = response.json()
        with open(INFO_OUTPUT_JSONL, "w", encoding="utf-8") as f:
            f.write(json.dumps(data, ensure_ascii=False) + "\n")
        print("✅ Appended JSON response to", INFO_OUTPUT_JSONL)
        return data

def roma_quota_info():
    INFO_OUTPUT_JSONL = "roma_quota_info.jsonl"
    url = "https://apigw.huawei.com/api/csb/roma-aistudio/train/quota/info"
    token_to_use = reuse_or_fetch_token(
        account_name="BMC_API_USER",
        account_secret="AESGCM:2856B514BE721213DBEADA0A5F37BD15:57AA692302F16DE42F5914D82F45B8F94EA1635A9D72912911C19BD748F63CD6E33C34BDB2AFD98DDF67A45F1A084DF2E7DED0C3",
    )
    print(f'Got token to use {token_to_use}')
    headers = {
        "Content-Type": "application/json",
        "Authorization": token_to_use,
        "X-HW-ID": "com.huawei.ipd.noproduct.tenant_z00515901.BJ",  # 这就是his gateway 绑定的应用id 而非roma的 bmc.ai.case，对所有roma应用通用
        "X-HW-APPKEY": "31y1UZJvij3YQ9QpZGk6dw==",  # apigateway api key 应用创建者在这里获取 https://console.his.huawei.com/apigw_portals/#/app/list
    }

    # Set your parameter values here
    query_params = {
        "appid":"com.app.bmc.ai.aicase", # 应用ID
        "jobtype": "EiWizardTrain", # 资源类型，可用值：EiWizardTrain
        "limittype": "GPU", # limittype
    }

    with httpx.Client(proxy=None, verify=False) as client:
        response = client.get(url, headers=headers, params=query_params)
        print("response  "* 3, response.status_code,  response.json())
        response.raise_for_status()
        data = response.json()
        with open(INFO_OUTPUT_JSONL, "w", encoding="utf-8") as f:
            f.write(json.dumps(data, ensure_ascii=False) + "\n")
        print("✅ Appended JSON response to", INFO_OUTPUT_JSONL)
        return data


def roma_get_pool_info():
    url = "https://csb.roma.huawei.com/csb/rest/saas/ei/eiWizard/train/pools/list"
    
    token_to_use = reuse_or_fetch_token(
        account_name="BMC_API_USER",
        account_secret="AESGCM:2856B514BE721213DBEADA0A5F37BD15:57AA692302F16DE42F5914D82F45B8F94EA1635A9D72912911C19BD748F63CD6E33C34BDB2AFD98DDF67A45F1A084DF2E7DED0C3",
    )
    print(f'Got token to use {token_to_use}')

    headers = {
        "Content-Type": "application/json",
        "Authorization": token_to_use,
        "csb_token": "11c05724-8866-432b-8957-142f29f1fc2c",
    }

    query_params = {
        "appid":"com.app.bmc.ai.aicase",
    }

    with httpx.Client(proxy=None, verify=False) as client:
        response = client.get(url, headers=headers, params=query_params)
        print("response  ", response.status_code,  json.dumps(response.json()))
        response.raise_for_status()

if __name__ == "__main__":
    
    # # 创建训练作业
    # roma_create_request()

    # # 查询训练作业
    roma_get_train()
    
    # # 停止训练作业 
    # roma_stop_train()
    
    # # 删除训练作业（权限不足） 
    # roma_delete_train()  # AuthErr: Your role of [AppSRERepresentitive] in app [com.app.bmc.ai.aicase] has no permission of [训练作业管理/删除训练作业(Training Jobs/deleteTrainJob)].
    
    # # 查询事件列表
    # roma_list_event()

    # # 查询配额
    # roma_quota_info()

    # roma_get_pool_info()
    # import dataclasses
    # print(json.dumps(dataclasses.asdict(RomaCreateRequest.from_template()), indent=2))